﻿using System;
using System.ComponentModel;
using System.Windows.Forms;

using JetBrains.Annotations;

using Rsdn.SmartApp;

namespace Rsdn.Janus
{
    /// <summary>
    /// Позволяет выполнить длительную работу в фоновом режиме,
    /// при этом на экране будет показываться визуализатор прогресса,
    /// а пользовательский интерфейс будет заблокирован.
    /// </summary>
    public static class ProgressWorker
    {
        public static void Run(
            [NotNull] IServiceProvider provider, 
            bool allowCancel, 
            [NotNull] Action<IProgressVisualizer> work)
        {
            Run(provider, allowCancel, work, null);
        }

        /// <exception cref="ArgumentNullException"><paramref name="provider" /> is <c>null</c>.</exception>
        public static void Run(
            [NotNull] IServiceProvider provider,
            bool allowCancel,
            [NotNull] Action<IProgressVisualizer> work,
            [CanBeNull] Action completeHandler)
        {
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            if (work == null)
            {
                throw new ArgumentNullException("work");
            }

            IProgressVisualizer progressVisualizer = null;

            Action<AsyncOperation> action =
                delegate
                    {
                        IProgressService progressService = provider.GetRequiredService<IProgressService>();
                        progressVisualizer = progressService.CreateVisualizer(allowCancel);

                        work(progressVisualizer);
                    };

            Action handler =
                delegate
                    {
                        progressVisualizer.Complete();
                        if (completeHandler != null)
                        {
                            completeHandler();
                        }
                    };

            AsyncHelper.RunAsync(action, handler);

            Application.DoEvents();
        }
    }
}